window.requestAnimFrame = (function(){
	  return  window.requestAnimationFrame       || 
			  window.webkitRequestAnimationFrame || 
			  window.mozRequestAnimationFrame    || 
			  window.oRequestAnimationFrame      || 
			  window.msRequestAnimationFrame     || 
			  function(callback, element){
				window.setTimeout(callback, 1000 / 50);
			  };
})();

var K = {
	Author1:"mi_kuncoro@yahoo.co.id",
	Version:"01.02 Betha",
	___cvs:null,
	___ctx:null,
	bufCvs:null,
	bufCtx:null,
	hitTolerance:1,
	hitCanvas:null,
	hitContext:null,
	stage:null,
	viewport:null,
	time:{ startTime:0, lastTime:0, curTime:0, deltaTime:0 },
	OID:0,
	get canvas() { return K.___cvs; },
	set canvas(v) {
		K.___cvs = v;
		K.___ctx = v.getContext("2d");
		K.bufCvs = document.createElement("canvas");
		K.bufCvs.width = v.width;
		K.bufCvs.height = v.height;
		K.bufCtx = K.bufCvs.getContext("2d");
		K.viewport = new K.Rectangle(0, 0, v.width, v.height);
		K.hitCanvas = document.createElement("canvas");
		K.hitCanvas.width = 1;
		K.hitCanvas.height = 1;
		K.hitContext = K.hitCanvas.getContext("2d");
	},
	get context() { return K.___ctx; }
};

K.getTimer = function() { return (new Date()).getTime() - K.time.startTime; };
K.updateTime = function(){
	var o = K.time;
	if (o.startTime == 0) {
		o.startTime =  (new Date()).getTime();
	} else {
		o.lastTime = o.curTime;
		o.curTime = K.getTimer();
		o.deltaTime = o.curTime - o.lastTime;
	}
	K.EventManager.resetLastKey();
};

K.init = function(cvs){
	K.canvas = cvs ? cvs : document.createElement("canvas");
	K.updateTime();
};

K.render = function(){
	K.stage.updateMatrix();	
	K.bufCtx.fillRect(0, 0, K.canvas.width, K.canvas.height);
	K.stage.paint(K.bufCtx);
	K.context.clearRect(0, 0, K.canvas.width, K.canvas.height);
	K.context.drawImage(K.bufCvs, 0, 0);
	K.updateTime();
};

K.getName = function(prefix){
	K.OID ++;
	return prefix + K.OID.toString();
};

K.cloneObject = function(v){
	var ret = {};
	for (var i in v){
		var g = v.__lookupGetter__(i), s = v.__lookupSetter__(i);
        if ( g || s ) {
            if ( g ) ret.__defineGetter__(i, g);
            if ( s ) ret.__defineSetter__(i, s);
         } else
             ret[i] = v[i];
	}
	return ret;
};
K.extend = function(a, b){
    for ( var i in b ) {
        var g = b.__lookupGetter__(i), s = b.__lookupSetter__(i);
        if ( g || s ) {
            if ( g ) a.__defineGetter__(i, g);
            if ( s ) a.__defineSetter__(i, s);
         } else
             a[i] = b[i];
    }
    return a;
};

K.Collection = function() {
	this.name = K.getName("collection_");
	this.names = [];
	this.objects = {};
};
K.Collection.prototype = {
	constructor:K.Collection,
	name:"Collection",
	names:[],
	objects:{},
	get array() { 
		var a = [];
		if (this.names.length == 0) return a;
		for (var i = 0; i < this.names.length; i++) {
			a.push(this.objects[this.names[i]]);
		}
		return a;
	},
	get length(){ return this.names.length; },
	getItem:function(v) { return this.objects[v]; },
	getItemAt:function(v) { return this.objects[this.names[v]]; },
	getItemByName:function(v){ return this.objects[v]; },
	addItem:function(v){
		if (v.name == null){
			v.name = "item_" + this.names.length.toString();
		}
		else if (this.names.indexOf(v.name) >= 0) {
			console.log(v.name + " already exist");
			return null;
		}
		this.names.push(v.name);
		this.objects[v.name] = v;
		return v.name;
	},
	clear:function(){
		this.names = [];
		this.objects = {};
	},
	removeItem:function(v){
		return this.removeItemAt(this.names.indexOf(v.name));
	},
	removeItemAt:function(v){
		if (i < 0) return;
		var o = this.objects[v];
		delete this.objects[v];
		this.names.splice(i, 1);
		return o;
	},
	removeItemByName:function(v){
		return this.removeItemAt(this.names.indexOf(v));
	},
	clone:function() {
		alert("K.Collection not implement clone()");
		return null;
	},
	dispose:function(){
		console.log("K.Collection not implement dispose()");
	}
};


K.P1 = Math.PI / 180;
K.P15 = K.P1 * 15;
K.P30 = K.P1 * 30;
K.P45 = Math.PI / 4;
K.P90 = Math.PI / 2;
K.P180 = Math.PI;
K.P270 = K.P90 * 3;
K.P360 = Math.PI * 2;
K.toDegree = function(v){ return v / P1; }
K.toRadian = function(v){ return v * P1; }

// Point

K.Point = function(xx, yy) {
	this.name =  K.getName("point_");
	this.x = xx || 0;
	this.y = yy || 0;
};
K.Point.prototype = {
	constructor:K.Point,
	name:"point",
	x:0, y:0,
	get angle() { return Math.atan2(this.y, this.x); },
	angleTo:function(x, y) { return Math.atan2(y - this.y, x - this.x); },
	get length() { return Math.sqrt(this.x * this.x + this.y * this.y); },
	add:function(x, y) { this.x += x; this.y += y; return this; },
	clone:function() { return new Point(this.x, this.y); },
	dispose:function() {},
	distanceTo:function(x, y) {
		var dx = x - this.x;
		var dy = y - this.y;
		return Math.sqrt(dx * dx + dy * dy);
	},
	subtract:function(x, y) { this.x -= x; this.y -= y; return this; },
	multiply:function(v) { this.x *= v; this.y *= v; return this; },
	normalize:function() {
		var d = this.length;
		if (d > 0 || d != 1){
			this.x /= d;
			this.y /= d;
		}
		return this;
	},
	toString:function() {
		return "[Point (x="+this.x+" y="+this.y+")]";
	}
};
K.Point.addPoint = function(p1, p2) {
	return new K.Point(p1.x + p2.x, p1.y + p2.y);
};
K.Point.anglePoint = function(p1, p2) {
	var dx = p1.x - p1.x;
	var dy = p2.y - p1.y;
	return Math.atan2(dy, dx);
};
K.Point.clonePoint = function(p) {
	return new K.Point(p.x, p.y);
};
K.Point.distancePoint = function(p1, p2) {
	var dx = p1.x - p1.x;
	var dy = p2.y - p1.y;
	return Math.sqrt(dx * dx + dy * dy);
};
K.Point.multiplyPoint = function(p, n) {
	return new K.Point(p.x * n, p.y * n);
};
K.Point.normalizePoint = function(p) {
	var d = Math.sqrt(p.x * p.x + p.y * p.y);
	if (d > 1)
	{
		p.x /= d;
		p.y /= d;
	}
};
K.Point.subtractPoint = function(p1, p2) {
	return new K.Point(p1.x - p2.x, p1.y - p2.y);
};

// Rectangle

K.Rectangle = function(xx, yy, ww, hh, offsetx, offsety){
	this.name =  K.getName("rectangle_");
	this.x = xx || 0;
	this.y = yy || 0;
	this.width = ww || 0;
	this.height = hh || 0;
	this.offsetX = offsetx || 0;
	this.offsetY = offsety || 0;
};
K.Rectangle.prototype = {
	constructor:K.Rectangle,
	name:"rectangle",
	x:0, y:0, width:0, height:0, offsetX:0, offsetY:0,
	get left() { return this.x; },
	get top() { return this.y; },
	get right() { return this.x + this.width; },
	get bottom() { return this.y + this.height; },
	clone:function() {
		var ret = new K.Rectangle(this.x, this.y, this.width, this.height);
		ret.offsetX = this.offsetX;
		ret.offsetY = this.offsetY;
		return ret;
	},
	containsPoint:function(xx, yy) {
		if (xx < this.x) return false;
		if (yy < this.y) return false;
		if (xx > this.right) return false;
		if (yy > this.bottom) return false;
		return true;
	},
	containsRect:function(v){
		if (v.x < this.x) return false;
		if (v.y < this.y) return false;
		if (v.right > this.right) return false;
		if (v.bottom > this.bottom) return false;
		return true;
	},
	dispose:function() {},
	intersects:function(v) {
		if (v.x > this.right) return false;
		if (v.y > this.bottom) return false;
		if (v.right < this.x) return false;
		if (v.bottom < this.y) return false;
		return true;
	},
	intersections:function(v){
		var ret = new K.Rectangle(
					Math.max(this.x, v.x),
					Math.max(this.y, v.y),
					0, 0);
		ret.width = Math.min(this.right, v.right) - ret.x;
		ret.height = Math.min(this.bottom, v.bottom) - ret.y;
		return ret;
	},
	toString:function() {
		return "[Rectangle (x="+this.x+" y="+this.y+" width="+this.width+" height="+this.height+")]";
	}
};

// Matrix 2D

K.Matrix = function(a, b, c, d, e, f) {
	this.name =  K.getName("matrix_");
	this.a = a || 1; this.b = b || 0; this.e = e || 0;
	this.c = c || 0; this.d = d || 1; this.f = f || 0;
}; 
K.Matrix.prototype = {
	constructor:K.Matrix,
	name:"matrix",
	a:1, b:0, c:0, d:1, e:0, f:0,
	setValues:function (aa, bb, cc, dd, ee, ff) {
		this.a = aa;
		this.b = bb;
		this.c = cc;
		this.d = dd;
		this.e = ee;
		this.f = ff;
		return this;
	},
	rotate:function (rads) {
		var nCos = Math.cos(rads);
		var nSin = Math.sin(rads);
		var tmp = this.a;
		this.a = nCos * tmp - nSin * this.b;
		this.b = nSin * tmp + nCos * this.b;
		tmp = this.c;
		this.c = nCos * tmp - nSin * this.d;
		this.d = nSin * tmp + nCos * this.d;
		tmp = this.e;
		this.e = nCos * tmp - nSin * this.f;
		this.f = nSin * tmp + nCos * this.f;

		return this;
	},
	scale:function (sx, sy) {
		this.a *= sx;
		this.b *= sy;
		this.c *= sx;
		this.d *= sy;
		this.e *= sx;
		this.f *= sy;
		return this;
	},
	translate:function (dx, dy) {
		this.e += this.a * dx + this.c * dy;
		this.f += this.b * dx + this.d * dy;
		return this;
	},
	prependRotation:function(rads){
		var nCos = Math.cos(rads);
		var nSin = Math.sin(rads);
		var tmp = this.a;
		this.a = nCos * tmp - nSin * this.b;
		this.b = nSin * tmp + nCos * this.b;
		tmp = this.c;
		this.c = nCos * tmp - nSin * this.d;
		this.d = nSin * tmp + nCos * this.d;
		return this;
	},
	prependTranslation:function (dx, dy) {
		this.e += dx;
		this.f += dy;
		return this;
	},
	prependScale:function (sx, sy) {
		this.a *= sx;
		this.b *= sy;
		this.c *= sx;
		this.d *= sy;
		return this;
	},
	multiply:function(m){
		var tmp = this.a;
		this.a = tmp * m.a + this.b * m.c;
		this.b = tmp * m.b + this.b * m.d;
		tmp = this.c;
		this.c = tmp * m.a + this.d * m.c;
		this.d = tmp * m.b + this.d * m.d;
		tmp = this.e;
		this.e = tmp * m.a + this.f * m.c + m.e;
		this.f = tmp * m.b + this.f * m.d + m.f;
		return this;
	},
	transformPoint:function(xx, yy){
		return {
			x : xx * this.a + yy * this.c + this.e,
			y : xx * this.b + yy * this.d + this.f
		};
	},
	invert:function () {
		var det = this.determinant();
		if (det !== 0) {
			var old = {
				a: this.a,
				b: this.b,
				c: this.c,
				d: this.d,
				e: this.e,
				f: this.f
			};
			this.a = old.d / det;
			this.b = -old.b / det;
			this.c = -old.c / det;
			this.d = old.a / det;
			this.e = (old.c * old.f - old.e * old.d) / det;
			this.f = (old.e * old.b - old.a * old.f) / det;
		}
		return this;
	},
	clone:function(){
		return new K.Matrix(this.a, this.b, this.c, this.d, this.e, this.f);
	},
	determinant:function(){
		return this.a * this.d - this.b * this.c;
	},
	dispose:function(){},
	equal:function(m){
		return
			this.a == m.a && this.b == m.b && this.c == m.c &&
			this.d == m.d && this.e == m.e && this.f == m.f;
	},
	identity:function(){
		this.a = this.d = this.i = 1;
		this.b = this.c = this.e = this.f = this.g = this.h = 0;
	},
	isIdentity:function () {
		return this.a === 1 && this.b === 0 && this.c === 0 && this.d === 1 && this.e === 0 && this.f === 0;
	},
	isInvertible:function () {
		return this.determinant() !== 0;
	}
};

/*
** I found many sprite-sheets having difference offsets each frame
** so we need facilitating specific offsets for every frame
*/
K.ImageSource = function(name, image, x, y, w, h, offsetX, offsetY){
	this.name = name || K.getName("imgSrc_");
	this.image = image || (new Image());
	if (arguments.length > 2) this.rect = new K.Rectangle(x, y, w, h, offsetX, offsetY);
	else this.rect = new K.Rectangle();
};
K.ImageSource.prototype = {
	name:"imageSource",
	image:null,
	rect:null,
	data:null,
	get x() { return this.rect.x; },
	set x(v) { this.rect.x = v; },
	get y() { return this.rect.y; },
	set y(v) { this.rect.y = v; },
	get width() { return this.rect.width; },
	set width(v) { this.rect.width = v; },
	get height() { return this.rect.height },
	set height(v) { this.rect.height = v; },
	get offsetX() { return this.rect.offsetX; },
	set offsetX(v) { this.rect.offsetX = v; },
	get offsetY() { return this.rect.offsetY; },
	set offsetY(v) { this.rect.offsetY = v; },
	get localRect() {
		var r = this.rect;
		return new K.Rectangle(r.offsetX, r.offsetY, r.width, r.height, 0, 0);
	},
	clone:function() { alert("ImageSource not implements clone()"); },
	dispose:function(){
		this.image = null;
	}
};

K.SheetAnimation = function(name, flip, start, end, loop, interval, prevAnim, nextAnim){
	this.name = name || K.getName("anim_");
	this.flip = flip || false;
	this.start = start || 0;
	this.end = end || 0;
	this.loop = loop || true;
	this.interval = interval || 10;
	this.prevAnim = prevAnim || null;
	this.nextAnim = nextAnim || null;
};
K.SheetAnimation.prototype = {
	name:"sheetAnimation",
	flip:false,
	start:0,
	end:0,
	loop:true,
	interval:250,
	prevAnim:null,
	nextAnim:null,
	data:null,
	dispose:function(){}
};

K.SheetData = function(name, img){
	this.name = name || K.getName("sheet_");
	this.image = img || (new Image());
	this.frames = [];
	this.animation = {};
};
K.SheetData.prototype = {
	constructor:K.SheetData,
	name:"sheetData",
	image:null,
	frames:null,
	animation:null,
	addAnimation:function(name, flip, start, end, loop, interval, prevAnim, nextAnim){
		this.animation[name] = new K.SheetAnimation(name, flip, start, end, loop, interval, prevAnim, nextAnim);
	},
	clone:function() {
		return new K.SheetData("newSheet", this.image);
	},
	dispose:function(){
		this.image = null;
		this.frames = [];
		this.animation = null;
	},
	checkFrame:function(animname, val){
		var anim = this.animation[animname];
		if (val < anim.start) return anim.loop ? anim.end : -1;
		if (val > anim.end) return anim.loop ? anim.start : -1;
		return val;
	},
	getFrame:function(animname, currentframe, time){
		var anim = this.animation[animname];
		var frm = (K.time.curTime - time) > anim.interval ? (currentframe + 1) : currentframe;
		if (frm > anim.end)  return anim.loop ? anim.start : -1;
		return frm
	},
	createImageSource:function(curframe){
		return this.updateImageSource(new K.ImageSource("src", this.image), curframe);
	},
	updateImageSource:function(src, curframe){
		if (curframe < 0 ||curframe >= this.frames.length) alert("frame out of range");
		if (src == null) src =  new K.ImageSource("src", this.image);
		src.rect = this.frames[curframe];
		return src;
	}
};

K.drawCommands = {
	moveTo:1,
	lineTo:2,
	quadraticCurveTo:3,
	bezierCurveTo:4,
	arc:5,
	arcTo:6,
	rect:7,
	clearRect:8,
	fillRect:9,
	strokeRect:10,
	shadowBlur:11,
	shadowColor:12,
	shadowOffsetX:13,
	shadowOffsetY:14,
	setAlpha:15,
	beginPath:16,
	closePath:17,
	clip:18,
	stroke:19,
	strokeStyle:20,
	lineWidth:21,
	lineCap:22,
	lineJoint:23,
	mitterLimit:24,
	fill:25,
	fillStyle:26,
	linear:27,
	radial:28,
	bitmap:29,
	image:30,
	font:31,
	textAlign:32,
	textBaseline:33,
	fillText:34,
	strokeText:35
};

K.createCircle = function(x, y, radius) {
	return {x:x, y:y, width:radius * 2, height:radius * 2, path:[[K.drawCommands.drawCircle, x, y, radius]]};
};

K.createRectangle = function(x, y, w, h){
	var p = [
		[K.drawCommands.moveTo, x, y],
		[K.drawCommands.lineTo, x + w, y],
		[K.drawCommands.lineTo, x + w, y + h],
		[K.drawCommands.lineTo, x, y + h],
		[K.drawCommands.lineTo, x, y]
	];
	return {x:x, y:y, width:w, height:h, path:p};
};

K.createRoundedRectangle = function(x, y, w, h, r1, r2, r3, r4){
	var p = []
	if (r1 > 0) {
		p.push([K.drawCommands.moveTo, x, y + r1]);
		p.push([K.drawCommands.quadraticCurveTo, x, y, x + r1, y]);
	} else {
		p.push([K.drawCommands.moveTo, x, y]);
	}
	if (r2 > 0) {
		p.push([K.drawCommands.lineTo, x + w - r2, y]);
		p.push([K.drawCommands.quadraticCurveTo, x + w, y, x + w, y + r2]);
	} else {
		p.push([K.drawCommands.lineTo, x + w, y]);
	}
	if (r3 > 0) {
		p.push([K.drawCommands.lineTo, x + w, y + h - r3]);
		p.push([K.drawCommands.quadraticCurveTo, x + w, y + h, x + w - r3, y + h]);
	} else {
		p.push([K.drawCommands.lineTo, x + w, y + h]);
	}
	if (r4 > 0) {
		p.push([K.drawCommands.lineTo, x + r4, y + h]);
		p.push([K.drawCommands.quadraticCurveTo, x, y + h, x, y + h - r4]);
	} else {
		p.push([K.drawCommands.lineTo, x, y + h]);
	}
	if (r1 > 0) {
		p.push([K.drawCommands.lineTo, x, y + r1]);
	} else {
		p.push([K.drawCommands.lineTo, x, y]);
	}
	return {x:x, y:y, width:w, height:h, path:p};
}

K.createPoly = function(x, y, points){
	var w1 = points[0].x + x;
	var h1 = points[0].y + y;
	var w2 = w1;
	var h2 = h1;
	var p = [];
	p.push([K.drawCommands.moveTo, x + points[0].x, y + points[0].y]);
	for (var i = 1; i < points.length; i++){
		p.push([K.drawCommands.lineTo, x + points[i].x, y + points[i].y]);
		w1 = Math.min(w1, p[i][1]);
		h1 = Math.min(h1, p[i][2]);
		w2 = Math.max(w2, p[i][1]);
		h2 = Math.max(h2, p[i][2]);
	}
	p.push([K.drawCommands.lineTo, x + points[0].x, y + points[0].y]);
	return {x:x, y:y, width:w2 - w1, height:h2 - h1, path:p};
};

K.createSimetry = function(x, y, numP, dist){
	if (numP < 3) numP = 3;
	
	var a = -K.P90;
	var s = K.P360 / numP;
	var p = [];
	p.push([K.drawCommands.moveTo, Math.cos(a) * dist + x, Math.sin(a) * dist + y]);
	var w1 = p[0][1];
	var h1 = p[0][2];
	var w2 = w1;
	var h2 = h1;
	a += s;
	for (var i = 0; i < numP; i++)
	{
		p.push([K.drawCommands.lineTo, Math.cos(a) * dist + x, Math.sin(a) * dist + y]);
		w1 = Math.min(w1, p[i][1]);
		h1 = Math.min(h1, p[i][2]);
		w2 = Math.max(w2, p[i][1]);
		h2 = Math.max(h2, p[i][2]);
		a += s;
	}
	a = -K.P90;
	p.push([K.drawCommands.lineTo, Math.cos(a) * dist + x, Math.sin(a) * dist + y]);
	return {x:x, y:y, width:w2 - w1, height:h2 - h1, path:p};
};

K.createStar = function(x, y, numP, dist, inner){
	if (numP < 3) numP = 3;
	var a = -K.P90;
	var s = K.P360 / (numP * 2);
	var d;
	var p = [];
	p.push([K.drawCommands.moveTo, Math.cos(a) * dist + x, Math.sin(a) * dist + y]);
	var w1 = p[0][1];
	var h1 = p[0][2];
	var w2 = w1;
	var h2 = h1;
	a += s;
	for (var i = 0; i <= (numP * 2); i++)
	{
		d = (i % 2 == 0) ? dist : inner;
		p.push([K.drawCommands.lineTo, Math.cos(a) * d + x, Math.sin(a) * d + y]);
		w1 = Math.min(w1, p[i][1]);
		h1 = Math.min(h1, p[i][2]);
		w2 = Math.max(w2, p[i][1]);
		h2 = Math.max(h2, p[i][2]);
		a += s;
	}
	a = -K.P90;
	p.push([K.drawCommands.lineTo, Math.cos(a) * dist + x, Math.sin(a) * dist + y]);
	return {x:x, y:y, width:w2 - w1, height:h2 - h1, path:p};
};


K.Graphics = function(owner){
	this.commands = [];
	this.owner = owner;
	this.minmax = {x1:20000, y1:20000, x2:-20000, y2:-20000};
	this.ownerUpdated = false;
};
K.Graphics.prototype = {
	constructor:K.Graphics,
	owner:null,
	clipTexture:false,
	clipCmd:null,
	commands:null,
	minmax:null,
	ownerUpdated:false,
	pathOnly:false,
	get x() { return (this.minmax.x2 < this.minmax.x1) ? 0 : this.minmax.x1; },
	get y() { return (this.minmax.y2 < this.minmax.y1) ? 0 : this.minmax.y1; },
	get width() { return (this.minmax.x2 < this.minmax.x1) ? 0 : (this.minmax.x2 - this.minmax.x1); },
	get height() { return (this.minmax.y2 < this.minmax.y1) ? 0 : (this.minmax.y2 - this.minmax.y1); },
	get localRect() {
		if (this.minmax.x2 < this.minmax.x1) return null;
		if (this.minmax.y2 < this.minmax.y1) return null;
		return new K.Rectangle(this.minmax.x1, this.minmax.y1,
					this.minmax.x2 - this.minmax.x1, this.minmax.y2 - this.minmax.y1);
	},
	updateOwner:function(){
		this.owner.localRect.x = this.x;
		this.owner.localRect.y = this.y;
		this.owner.localRect.width = this.width;
		this.owner.localRect.height = this.height;
		this.ownerUpdated = true;
	},
	setMinMax:function(x, y, w, h){
		this.minmax.x1 = x;
		this.minmax.y1 = y;
		this.minmax.x2 = x + w;
		this.minmax.y2 = y + h;
		this.owner.updated = false;
	},
	checkMinMax:function(x, y) {
		this.minmax.x1 = Math.min(this.minmax.x1, x);
		this.minmax.y1 = Math.min(this.minmax.y1, y);
		this.minmax.x2 = Math.max(this.minmax.x2, x);
		this.minmax.y2 = Math.max(this.minmax.y2, y);
		this.owner.updated = false;
	},
	checkPolyMinMax:function(p){
		this.resetMinMax();
		for (var i = 0; i < p.length; i++) {
			this.checkMinMax(p[i].x, p[i].y);
		}
	},
	resetMinMax:function(){
		this.minmax.x1 = this.minmax.y1 = -20000;
		this.minmax.x2 = this.minmax.y2 = 20000;
		this.owner.updated = false;
	},
	addPath:function(v){
		this.commands.push(v);
	},
	addPaths:function(v){
		for (var i = 0; i < v.length; i++){
			this.commands.push(v[i]);
			if (v[1].x != undefined)  checkMinMax(v[i].x, v[i].y);
		}
	},
	addGeom:function(g){
		this.addPaths(g.path);
	},
	clear:function(){
		this.commands = [];
		this.resetMinMax();
	},
	clearRect:function(x, y, w, h){
		this.addPath([K.drawCommands.clearRect, x, y, w, h]);
	},
	drawCircle:function(x, y, r){
		this.commands.push([K.drawCommands.arc, x, y, r, K.P360, false]);
		this.setMinMax(x - r, y - r, r * 2, r * 2);
	},
	drawEllipse:function(x, y, w, h){
		var r = Math.min(w/2, h/2);
		this.addGeom( K.createRoundedRectangle(x, y, w, h, r, r, r, r));
		this.setMinMax(x, y, w, h);
	},
	drawRect:function(x, y, w, h){
		this.addGeom( K.createRectangle(x, y, w, h));
		this.setMinMax(x, y, w, h);
	},
	drawRoundRect:function(x, y, w, h, r1, r2, r3, r4){
		this.addGeom( K.createRoundedRectangle(x, y, w, h, r1, r2, r3, r4));
		this.setMinMax(x, y, w, h);
	},
	drawPolygon:function(x, y, points){
		this.addGeom( K.createPolygon(x, y, points));
	},
	drawSimetry:function(x, y, numPoint, distance){
		this.addGeom( K.createSimetry(x, y, numPoint, distance));
		this.setMinMax(x, y, distance, distance);
	},
	drawStar:function(x, y, numPoint, distance, innerDistance){
		this.addGeom( K.createStar(x, y, numPoint, distance, innerDistance));
		this.setMinMax(x, y, distance, distance);
	},
	drawBitmap:function(img, offsetX, offsetY){
		this.addPath([K.drawCommands.bitmap, img, offsetX, offsetY]);
		this.setMinMax(offsetX, offsetY, Math.abs(offsetX * 2), Math.abs(offsetY * 2));
	},
	drawText:function(txt, x, y, maxW, font, align, baseLine, stroke, fill){
		this.addPath([K.drawCommands.font, font]);
		this.addPath([K.drawCommands.textAlign, align]);
		this.addPath([K.drawCommands.textBaseline, baseLine]);
		if (fill) this.addPath([K.drawCommands.fillText, txt, x, y, maxW]);
		if (stroke) this.addPath([K.drawCommands.strokeText, txt, x, y, maxW]);
		//this.setMinMax(x, y, maxw, maxw);
	},
	moveTo:function(x, y){
		this.addPath([K.drawCommands.moveTo, x, y]);
		this.checkMinMax(x, y);
	},
	lineTo:function(x, y){
		this.addPath([K.drawCommands.lineTo, x, y]);
		this.checkMinMax(x, y);
	},
	arc:function(x,  y, r1, r2, clockWise){
		this.addPath([K.drawCommands.arc, x, y, r1, r2, clockWise]);
		checkMinMax(x, y);
	},
	arcTo:function(x1,  y1, x2, y2, r){
		this.addPath([K.drawCommands.arc, x1, y1, x2, y2, r]);
		this.checkMinMax(x, y);
	},
	curveTo:function(a, b, c, d, e, f){
		if (f) {
			this.addPath([K.drawCommands.bezierCurveTo, a, b, c, d, e, f]);
			this.checkMinMax(e, f);
		} else {
			this.addPath([K.drawCommands.quadraticCurveTo, a, b, c, d]);
			this.checkMinMax(c, d);
		}
	},
	bezierCurveTo:function(x1, y1, x2, y2, x, y){
		this.addPath([K.drawCommands.bezierCurveTo, x1, y1, x2, y2, x, y]);
		this.checkMinMax(x, y);
	},
	quadraticCurveTo:function(cpx, cpy, x, y){
		this.addPath([K.drawCommands.quadraticCurveTo, cpx, cpy, x, y]);
		this.checkMinMax(x, y);
	},
	beginPath:function() { this.addPath([K.drawCommands.beginPath]); this.resetMinMax(); },
	closePath:function() { this.addPath([K.drawCommands.closePath]); },
	clip:function(){ this.addPath([K.drawCommands.clip]); },
	setShadow:function(color, blur, offsetX, offsetY){
		this.addPath([K.drawCommands.shadowColor, color]);
		this.addPath([K.drawCommands.shadowBlur, blur]);
		this.addPath([K.drawCommands.shadowOffsetX, offsetX]);
		this.addPath([K.drawCommands.shadowOffsetY, offsetY]);
	},
	lineStyle:function(thickness, color){
		this.addPath([K.drawCommands.strokeStyle, color]);
		this.addPath([K.drawCommands.lineWidth, thickness]);
	},
	beginFill:function(color, alpha){
		this.addPath([K.drawCommands.fillStyle, color]);
		this.addPath([K.drawCommands.setAlpha, alpha||1.0]);
	},	
	beginBitmapFill:function(texture, a, b, c, d, e, f, g, h){
		this.addPath([K.drawCommands.image, texture, a, b, c, d, e, f, g, h]);
	},
	beginGradientFill:function(type, colors, ratios, a, b, c, d, e, f){
		if (type == "linear") {
			this.addPath([K.drawCommands.linear, colors, ratios, a, b, c, d]);
		}
		else {
			this.addPath([K.drawCommands.radial, colors, ratios, a, b, c, d, e, f]);
		}
	},
	endFill:function(){
		this.addPath([K.drawCommands.fill]);
		this.addPath([K.drawCommands.stroke]);
	},
	rect:function(x, y, w, h){
		this.addPath([K.drawCommands.rect, x, y, w, h]);
		this.setMinMax(x, y, w, h);
	},
	fillRect:function(x, y, w, h){
		this.addPath([K.drawCommands.fillRect, x, y, w, h]);
		this.setMinMax(x, y, w, h);
	},
	strokeRect:function(x, y, w, h){
		this.addPath([K.drawCommands.strokeRect, x, y, w, h]);
		this.setMinMax(x, y, w, h);
	},
	stroke:function(){
		this.addPath([K.drawCommands.stroke]);
	},
	fill:function(){
		this.addPath([K.drawCommands.fill]);
	},
	doCommand:function(c, cmd){
		var j, grd;
		switch (cmd[0]){
			case K.drawCommands.moveTo:
				c.moveTo(cmd[1], cmd[2]);
				break;
			case K.drawCommands.lineTo:
				c.lineTo(cmd[1], cmd[2]);
				break;
			case K.drawCommands.quadraticCurveTo:
				c.quadraticCurveTo(cmd[1], cmd[2], cmd[3], cmd[4]);
				break;
			case K.drawCommands.bezierCurveTo:
				c.bezierCurveTo(cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6]);
				break;
			case K.drawCommands.arc:
				c.arc(cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6]);
				break;
			case K.drawCommands.arcTo:
				c.arcTo(cmd[1], cmd[2], cmd[3], cmd[4], cmd[5]);
				break;
			case K.drawCommands.rect:
				c.rect(cmd[1], cmd[2], cmd[3], cmd[4]);
				break;
			case K.drawCommands.clearRect:
				c.clearRect(cmd[1], cmd[2], cmd[3], cmd[4]);
				break;
			case K.drawCommands.fillRect:
				c.fillRect(cmd[1], cmd[2], cmd[3], cmd[4]);
				break;
			case K.drawCommands.strokeRect:
				c.strokeRect(cmd[1], cmd[2], cmd[3], cmd[4]);
				break;
			case K.drawCommands.shadowBlur:
				c.shadowBlur = cmd[1];
				break;
			case K.drawCommands.shadowColor:
				c.shadowColor = cmd[1];
				break;
			case K.drawCommands.shadowOffsetX:
				c.shadowOffsetX = cmd[1];
				break;
			case K.drawCommands.shadowOffsetY:
				c.shadowOffsetY = cmd[1];
				break;
			case K.drawCommands.setAlpha:
				c.setAlpha(cmd[1]);
				break;
			case K.drawCommands.beginPath:
				c.beginPath();
				break;
			case K.drawCommands.closePath:
				c.closePath();
				break;
			case K.drawCommands.clip:
				c.clip();
				break;
			case K.drawCommands.stroke:
				c.stroke();
				break;
			case K.drawCommands.strokeStyle:
				c.strokeStyle = cmd[1];
				break;
			case K.drawCommands.lineWidth:
				c.lineWidth = cmd[1];
				break;
			case K.drawCommands.lineCap:
				c.lineCap = cmd[1];
				break;
			case K.drawCommands.lineJoint:
				c.lineJoint = cmd[1];
				break;
			case K.drawCommands.mitterLimit:
				c.mitterLimit = cmd[1];
				break;
			case K.drawCommands.fill:
				if (this.clipTexture){
					c.clip();
					//var r = this.localRect;
					var ccmd = this.clipCmd;
					c.drawImage(ccmd[1],
								ccmd[2], ccmd[3], ccmd[4], ccmd[5],
								ccmd[6], ccmd[7], ccmd[8], ccmd[9]);
								//r.x, r.y, r.width, r.height);
				} else {
					c.fill();
				}
				break;
			case K.drawCommands.fillStyle:
				c.fillStyle = cmd[1];
				break;
			case K.drawCommands.linear:
				grd = c.createLinearGradient(cmd[3], cmd[4], cmd[5], cmd[6]);
				for (j = 0; j < cmd[1].length; j++) {
					grd.addColorStop(cmd[2][j], cmd[1][j]);
				}
				c.fillStyle = grd;
				break;
			case K.drawCommands.radial:
				grd = c.createRadialGradient(cmd[3], cmd[4], cmd[5], cmd[6], cmd[7], cmd[8]);
				for (j = 0; j < cmd[1].length; j++) {
					grd.addColorStop(cmd[2][j], cmd[1][j]);
				}
				c.fillStyle = grd;
				break;
			case K.drawCommands.bitmap:
				c.drawImage(cmd[1], cmd[2], cmd[3]);
			case K.drawCommands.image:
				this.clipCmd = cmd;
				this.clipTexture = true;
				break;
			case K.drawCommands.font:
				c.font = cmd[1];
				break;
			case K.drawCommands.textAlign:
				c.textAlign = cmd[1];
				break;
			case K.drawCommands.textBaseline:
				c.textBaseLine = cmd[1];
				break;
			case K.drawCommands.fillText:
				if (cmd[4]) {
					c.fillText(cmd[1], cmd[2], cmd[3], cmd[4]);
				} else {
					c.fillText(cmd[1], cmd[2], cmd[3]);
				}
				break;
			case K.drawCommands.strokeText:
				if (cmd[4]){
					c.strokeText(cmd[1], cmd[2], cmd[3], cmd[4]);
				} else {
					c.strokeText(cmd[1], cmd[2], cmd[3]);
				}
				break;
		}
		
	},
	paint:function(c){
		if (this.ownerUpdated == false) this.updateOwner();
		if (this.commands.length == 0) return;
		this.clipTexture = false;
		c.strokeStyle = null;
		c.fillStyle = null;
		for (var i = 0; i < this.commands.length; i++){
			this.doCommand(c, this.commands[i]);
		}
	},
	dispose:function(){
		this.clipCmd = null;
		this.commands = null;
		this.owner = null;
	}
};


K.hitMethods = {
	DISTANCE_HIT:"distanceHit",
	GLOBAL_HIT:"globalHit",
	LOCAL_HIT:"localHit",
	PIXEL_HIT:"pixelHit"
};

K.Events = {
	MOUSE_OVER:"mouseover",
	MOUSE_DOWN:"mousedown",
	MOUSE_MOVE:"mousemove",
	MOUSE_UP:"mouseup",
	MOUSE_OUT:"mouseout",
	CLICK:"click",
	DOUBLE_CLICK:"dblclick",
	TOUCH_START:"touchstart",
	TOUCH_MOVE:"touchmove",
	TOUCH_END:"touchend",
	TOUCH_STOP:"touchstop",
	KEY_DOWN:"keydown",
	KEY_UP:"keyup",
	START_DRAG:"startdrag",
	END_DRAG:"enddrag",
	COMPLETE:"complete",
	STAGE_RESIZE:"stageresize",
	RESIZE:"resize"
};


K.Event = function(type, bubble, data){
	this.eventType = type;
	this.bubble = bubble;
	this.data = data;
};
K.Event.prototype = {
	eventType:null,
	data:null,
	deviceType:null,
	target:null,
	currentTarget:null,
	bubble:false,
	clone:function(){
		var ret = new K.Event(this.eventType, this.bubble, this.data);
		ret.deviceType = this.deviceType;
		ret.currentTarget = this.currentTarget;
		return ret;
	},
	dispose:function(){
		data = null;
		target = null;
		currentTarget = null;
	}
};


K.EventManager = {
	lastKeyDown:null,
	lastKeyUp:null,
	keyDown:{},
	resetLastKey:function(){
		this.lastKeyUp = null;
		this.lastKeyDown = null;
	},
	processKeyboardEvent:function(e){
		var oEvent = new K.Event(e.type, true, {keyCode:e.keyCode});
		oEvent.deviceType = "keyboard";
		var s = "key" + e.keyCode.toString();
		if (e.type == "keydown") {
			this.lastKeyDown = s;
			this.keyDown[s] = true;
		} else {
			this.lastKeyUp = s;
			this.keyDown[s] = false;
		}
		K.stage.dispatchEvent(oEvent);
	},
	processMouseEvent:function(e){
		var oEvent = new K.Event(e.type, true, {mouseX:e.offsetX, mouseY:e.offsetY});
		oEvent.deviceType = "mouse";
		K.stage.mouseX = e.offsetX;
		K.stage.mouseY = e.offsetY;
		K.stage.dispatchEvent(oEvent);
	},
	processTouchEvent:function(e){
		var oEvent = new K.Event(e.type, true, {mouseX:e.offsetX, mouseY:e.offsetY});
		oEvent.deviceType = "touch";
		K.stage.mouseX = e.offsetX;
		K.stage.mouseY = e.offsetY;
		K.stage.dispatchEvent(oEvent);
	},
	start:function(){
		var c = K.canvas;
		c.addEventListener("mouseover",	function(e) { K.EventManager.processMouseEvent(e); });
		c.addEventListener("mousedown",	function(e) { K.EventManager.processMouseEvent(e); });
		c.addEventListener("mousemove",	function(e) { K.EventManager.processMouseEvent(e); });
		c.addEventListener("mouseup",	function(e) { K.EventManager.processMouseEvent(e); });
		c.addEventListener("mouseout",	function(e) { K.EventManager.processMouseEvent(e); });
		c.addEventListener("click",		function(e) { K.EventManager.processMouseEvent(e); });
		c.addEventListener("dblclick",	function(e) { K.EventManager.processMouseEvent(e); });
		c.addEventListener("touchstart",function(e) { K.EventManager.processTouchEvent(e); });
		c.addEventListener("touchmove",	function(e) { K.EventManager.processTouchEvent(e); });
		c.addEventListener("touchend",	function(e) { K.EventManager.processTouchEvent(e); });
		c.addEventListener("resize",	function(e) { K.EventManager.processTouchEvent(e); });
		document.addEventListener("keydown",function(e) { K.EventManager.processKeyboardEvent(e); });
		document.addEventListener("keyup",	function(e) { K.EventManager.processKeyboardEvent(e); });
	},
	stop:function(){
		c.removeEventListener("mouseover",	function(e) { K.EventManager.processMouseEvent(e); });
		c.removeEventListener("mousedown",	function(e) { K.EventManager.processMouseEvent(e); });
		c.removeEventListener("mousemove",	function(e) { K.EventManager.processMouseEvent(e); });
		c.removeEventListener("mouseup",	function(e) { K.EventManager.processMouseEvent(e); });
		c.removeEventListener("mouseout",	function(e) { K.EventManager.processMouseEvent(e); });
		c.removeEventListener("click",		function(e) { K.EventManager.processMouseEvent(e); });
		c.removeEventListener("dblclick",	function(e) { K.EventManager.processMouseEvent(e); });
		c.removeEventListener("touchstart", function(e) { K.EventManager.processTouchEvent(e); });
		c.removeEventListener("touchmove",	function(e) { K.EventManager.processTouchEvent(e); });
		c.removeEventListener("touchend",	function(e) { K.EventManager.processTouchEvent(e); });
		c.removeEventListener("resize",	function(e) { K.EventManager.processMouseEvent(e); });	
		document.removeEventListener("keydown", function(e) { K.EventManager.processKeyboardEvent(e); });
		document.removeEventListener("keyup",	function(e) { K.EventManager.processKeyboardEvent(e); });
	}
};

K.EventDispatcher = function(){
	this.mouseHitMethod = K.hitMethods.LOCAL_HIT;
	this.objListener = {};
};
K.EventDispatcher.prototype = {
	constructor:K.EventDispatcher,
	objListenener:null,
	mouseHitMethod:null,
	hasEventListener:function() {
		var ret = false;
		for (var o in this.objListener){
			if (o.length > 0) {
				ret - true;
				break;
			}
		}
		return ret;
	},
	addEventListener:function(eType, eCallback){
		if (!this.objListener[eType]) this.objListener[eType] = [];
		this.objListener[eType].push(eCallback);
	},
	removeEventListener:function(eType, eCallnack){
		if (!this[eType]) return;
		var i = this[eType].indexOf(eCallback);
		if (i < 0) return;
		this[eType].splice(i, 1);
	},
	removeEventListeners:function() {
		for (var o in this.objListener) {
			o.length = 0;
		}
	},
	broadcastEvent:function(e){
		if (!this.objListener[e.eventType]) return;
		var a = this.objListener[e.eventType];
		if (a.length == 0) return;
		e.currentTarget = this;
		for (var i = 0; i < a.length; i++) {
			a[i](e);
		}
	},
	dispatchEvent:function(e){
		if (this.objListener[e.eventType]) this.broadcastEvent(e);
	}
};

K.Sprite = function(name, x, y, obj){
	
	this.initialize(name, { x:x, y:y});
};
K.Sprite.prototype = K.cloneObject(K.EventDispatcher.prototype);
K.Sprite.prototype.constructor = K.Sprite;
K.Sprite.prototype.name = "Sprite";
K.Sprite.prototype._x = 0;
K.Sprite.prototype._y = 0;
K.Sprite.prototype._r = 0;
K.Sprite.prototype._sx = 1.0;
K.Sprite.prototype._sy = 1.0;
K.Sprite.prototype.zIndex = 0;
K.Sprite.prototype.centerX = 0;
K.Sprite.prototype.centerY = 0;
K.Sprite.prototype.mouseX = 0;
K.Sprite.prototype.mouseY = 0;
K.Sprite.prototype.localRect = null;
K.Sprite.prototype.lMat = null;
K.Sprite.prototype.wMat = null;
K.Sprite.prototype.iMat = null;
K.Sprite.prototype.dirty = true;
K.Sprite.prototype.wdirty = true;
K.Sprite.prototype.children = null;
K.Sprite.prototype.parent = null;
K.Sprite.prototype.graphics = null;
K.Sprite.prototype.src = null;
K.Sprite.prototype.visible = true;
K.Sprite.prototype.data = null;
K.Sprite.prototype.__defineGetter__("localX", function() { return this.localRect.x; });
K.Sprite.prototype.__defineGetter__("localY", function() { return this.localRect.y; });
K.Sprite.prototype.__defineGetter__("localH", function() { return this.localRect.height; });
K.Sprite.prototype.__defineGetter__("localW", function() { return this.localRect.width; });
K.Sprite.prototype.__defineGetter__("worldRect", function(){
	var x1 = this.localX;
	var x2 = x1 + this.localW;
	var y1 = this.localY;
	var y2 = y1 + this.localH;
	var p1 = this.localToGlobal(x1, y1);
	var p2 = this.localToGlobal(x2, y1);
	var p3 = this.localToGlobal(x2, y2);
	var p4 = this.localToGlobal(x1, y2);
	var minX = Math.min(p1.x, Math.min(p2.x, Math.min(p3.x, p4.x)));
	var minY = Math.min(p1.y, Math.min(p2.y, Math.min(p3.y, p4.y)));
	var maxX = Math.max(p1.x, Math.max(p2.x, Math.max(p3.x, p4.x)));
	var maxY = Math.max(p1.y, Math.max(p2.y, Math.max(p3.y, p4.y)));
	return new K.Rectangle(minX, minY, maxX-minX, maxY - minY);
});
K.Sprite.prototype.__defineGetter__("localMatrix", function() {
	if (this.dirty)
	{
		if(!this.lMat) this.lMat = new K.Matrix();
		this.lMat.identity();
		if (this.rotation != 0) this.lMat.prependRotation(this.rotation);
		if (this.scaleX != 1 || this.scaleY != 1) this.lMat.prependScale(this.scaleX, this.scaleY);
		this.lMat.prependTranslation(this.x, this.y);
		this.dirty = false;
		this.wdirty = true;
	}
	return this.lMat;
});
K.Sprite.prototype.__defineGetter__("worldMatrix", function() {
	if (this.wdirty) this.updateMatrix();
	return this.wMat;
});
K.Sprite.prototype.__defineGetter__("invertedMatrix", function() {
	if (this.wdirty) this.updateMatrix();
	return this.iMat;
});
K.Sprite.prototype.__defineGetter__("x", function() { return this._x; });
K.Sprite.prototype.__defineSetter__("x", function(v) {
	this._x = v;
	this.dirty = true;
});
K.Sprite.prototype.__defineGetter__("y", function() { return this._y; });
K.Sprite.prototype.__defineSetter__("y", function(v) {
	this._y = v;
	this.dirty = true;
});
K.Sprite.prototype.__defineGetter__("height", function() { return this.localH * this._sy; });
K.Sprite.prototype.__defineSetter__("height", function(v) { if (this.localH > 0) this._sy = v / this.localH; });
K.Sprite.prototype.__defineGetter__("width", function() { return this.localW * this._sx; });
K.Sprite.prototype.__defineSetter__("width", function(v) { if (this.localW > 0) this._sx = v / this.localW; });
K.Sprite.prototype.__defineGetter__("rotation", function() { return this._r; });
K.Sprite.prototype.__defineSetter__("rotation", function(v) { this._r = v; this.dirty = true; });
K.Sprite.prototype.__defineGetter__("scaleX", function() { return this._sx; });
K.Sprite.prototype.__defineSetter__("scaleX", function(v) { this._sx = v; this.dirty = true; });
K.Sprite.prototype.__defineGetter__("scaleY", function() { return this._sy; });
K.Sprite.prototype.__defineSetter__("scaleY", function(v) { this._sy = v; this.dirty = true; });
K.Sprite.prototype.__defineGetter__("imageSource", function() { return this.src; });
K.Sprite.prototype.__defineSetter__("imageSource", function(v) { this.setImageSource(v); });
K.Sprite.prototype.__defineGetter__("stage", function() { return K.stage; });
K.Sprite.prototype.__defineGetter__("numChildren", function(){ return this.children.length; });
K.Sprite.prototype.__defineGetter__("childrenArray", function() { return this.children.array; });
K.Sprite.prototype.getChildAt = function(v){ return this.children.getItemAt(v); };
K.Sprite.prototype.getChildByName = function(v){ return this.children.getItemByName(v); };
K.Sprite.prototype.getBounds = function(v){
	var lr = this.localRect;
	var p1 = this.localToGlobal(lr.x, lr.y);
	var p2 = this.localToGlobal(lr.right, lr.y);
	var p3 = this.localToGlobal(lr.right, lr.bottom);
	var p4 = this.localToGlobal(lr.x, lr.bottom);
	p1 = v.globalToLocal(p1.x, p1.y);
	p2 = v.globalToLocal(p2.x, p2.y);
	p3 = v.globalToLocal(p3.x, p3.y);
	p4 = v.globalToLocal(p4.x, p4.y);
	var minX = Math.min(p1.x, Math.min(p2.x, Math.min(p3.x, p4.x)));
	var minY = Math.min(p1.y, Math.min(p2.y, Math.min(p3.y, p4.y)));
	var maxX = Math.max(p1.x, Math.max(p2.x, Math.max(p3.x, p4.x)));
	var maxY = Math.max(p1.y, Math.max(p2.y, Math.max(p3.y, p4.y)));
	return new K.Rectangle(minX, minY, maxX-minX, maxY - minY);
};
K.Sprite.prototype.getObjectsUnderPoint = function(x, y, out){
	if (out == undefined) out = [];
	if (this.globalBounds.containtsPoint(x, y) == false) return out;
	out.push(this);
	if (this.hitTestPoint(x, y, true)) return out;
	if (this.children.length == 0) return out;
	var a = this.children.array;
	while (a.length > 0) {
		a.pop().getObjectsUnderPoint(x, y, out);
	};
	return out;
};
K.Sprite.prototype.setImageSource = function(v) {
	this.src = v;
	if (v != null){
		this.localRect.x = v.offsetX;
		this.localRect.y = v.offsetY;
		this.localRect.width = v.width;
		this.localRect.height = v.height;
	}
};
K.Sprite.prototype.addChild = function(v){
	v.parent = this;
	if (v.zIndex == null) v.zIndex = this.children.length;
	this.children.addItem(v);
};
K.Sprite.prototype.removeChild = function(v){
	if (v == null) return null;
	v.parent = null;
	return this.children.removeItem(v);
};
K.Sprite.prototype.removeChildAt = function(v){
	var o = this.children.removeItemAt(v);
	if (o) o.parent = null;
	return o;
};
K.Sprite.prototype.removeChildByName = function(v){
	var o = this.children.removeItemByName(v);
	if (o) o.parent = null;
	return o;
};
K.Sprite.prototype.updateMatrix = function(){
	this.wMat = (!this.parent)
		? this.localMatrix.clone()
		: this.localMatrix.clone().multiply(this.parent.worldMatrix);
	this.iMat = this.wMat.clone().invert();
	this.wdirty = false;
	if (this.children.length == 0) return;
	var a = this.children.array;
	while (a.length > 0) {
		a.pop().updateMatrix(this.wMat);
	}
};
K.Sprite.prototype.localToGlobal = function(px, py){
	return this.worldMatrix.transformPoint(px, py);
};
K.Sprite.prototype.globalToLocal = function(px, py){
	return this.invertedMatrix.transformPoint(px, py);
};
K.Sprite.prototype.hitLocal = function(obj){
	var r1 = obj.localRect.clone();
	var p1 = obj.localToGlobal(r1.x, r1.y);
	var p2 = obj.localToGlobal(r1.x + r1.width, r1.y);
	var p3 = obj.localToGlobal(r1.x + r1.width, r1.y + r1.height);
	var p4 = obj.localToGlobal(r1.x + r1.width, r1.y + r1.height);
	p1 = this.globalToLocal(p1.x, p1.y);
	p2 = this.globalToLocal(p2.x, p2.y);
	p3 = this.globalToLocal(p3.x, p3.y);
	p4 = this.globalToLocal(p4.x, p4.y);
	var r2 = this.localRect;
	if (r2.containsPoint(p1.x, p1.y)){
		return true;
	} else if (r2.containsPoint(p2.x, p2.y)){
		return true;
	} else if (r2.containsPoint(p3.x, p3.y) == true){
		return true;
	} else if (r2.containsPoint(p4.x, p4.y) == true){
		return true;
	}
	return false;
};
K.Sprite.prototype.hitTestPoint = function(x, y, hitMethod){
	var p = this.globalToLocal(x, y);
	if (hitMethod == K.hitMethods.PIXEL_HIT) {
		var c = K.hitContext;
		c.canvas.width = 0;
		c.canvas.width = 1;
		this.paintSelf(c, 1, 0, 0, 1, -p.x, -p.y);
		var dat = c.getImageData(0, 0, 1, 1).data;
		return (dat[3] >= K.hitTolerance);
	}
	return this.localRect.containsPoint(p.x, p.y);
};
K.Sprite.prototype.hitTestObject = function(obj, hitMethod){
	var r1, r2;
	var collide = false;
	if (this.hitMethods == K.hitMethods.GLOBAL_HIT) {
		return this.worldRect.intersects(obj.worldRect);
	} else {
		collide = this.hitLocal(obj);
		if (collide == false) collide = obj.hitLocal(this);
		if (collide == false) return false;
		if (hitMethod == K.hitMethods.LOCAL_HIT) return collide;
	}	
	
	//console.log("try pixel hit because collide = " + collide);
	var rect = this.worldRect.intersections(obj.worldRect);
	colllide = false;
	
	var c = K.hitContext;
	var m = this.worldMatrix;
	c.canvas.width = 0;
	c.canvas.width = K.canvas.width;
	c.canvas.height = K.canvas.height;
	c.save();
	c.clearRect(0, 0, 1, 1);
	this.paintSelf(c, m.a, m.b, m.c, m.d, m.e, m.f);
	c.restore();
	var da = c.getImageData(rect.x, rect.y, rect.width, rect.height).data;
	
	m = obj.worldMatrix;
	c.canvas.width = 0;
	c.canvas.width = K.canvas.width;
	c.canvas.height = K.canvas.height;
	c.save();
	c.clearRect(0, 0, 1, 1);
	obj.paintSelf(c, m.a, m.b, m.c, m.d, m.e, m.f);
	c.restore();
	var db = c.getImageData(rect.x, rect.y, rect.width, rect.height).data;
	
	var i = 0;
	while (i < da.length)
	{
		if ( da[i] > 0 || da[i+1] > 0 || da[i+2] > 0 || da[i+3] >= K.hitTolerance) {
			if (db[i] > 0 || db[i+1] > 0 || db[i+2] > 0 || db[i+3] >= K.hitTolerance) {                                      
				colllide = true;
				break;
			}
		}	
		i += 4;
	}
	
	return colllide;
};
K.Sprite.prototype.paint = function(c){
	var mat = this.worldMatrix;
	if (this.visible) this.paintSelf(c, mat.a, mat.b, mat.c, mat.d, mat.e, mat.f);
	if (this.children.length == 0) return;
	var a = this.children.array;
	a.sort(function(a, b) {
		if (a.zIndex>b.zIndex) return 1;
		if (a.zIndex<b.zIndex) return -1;
		return 0;
	});
	for (var i = 0; i < a.length; i++){
		a[i].paint(c);
	}
};
K.Sprite.prototype.paintSelf = function(c, p1, p2, p3, p4, p5, p6){
	c.save();
	c.setTransform(p1, p2, p3, p4, p5, p6);
	if (this.graphics.commands.length > 0) this.graphics.paint(c);
	if (this.src) {
		c.drawImage(this.src.image, this.src.x, this.src.y, this.src.width, this.src.height,
					this.src.offsetX, this.src.offsetY, this.src.width, this.src.height);
	}
	c.restore();
};
K.Sprite.prototype.initialize = function(cname, o){
	this.name = cname || K.getName("sprite_");
	this.mouseHitMethod = K.hitMethods.LOCAL_HIT;
	this.objListener = {};
	this.graphics = new K.Graphics(this);
	this.localRect = new K.Rectangle(0, 0, 0, 0);
	this.lMat = new K.Matrix();
	this.children = new K.Collection();
	this.iso = false;
	this.visible = true;
	this.data = {};
	this.dirty = true;
	this.wdirty = true;
	this._x = 0;
	this._y = 0;
	this._r = 0;
	this._sx = 1.0;
	this._sy = 1.0;
	this.centerX = 0;
	this.centerY = 0;
	if (o == undefined) return;	
	for (var s in o) {
		this[s] = o[s];
	}
};
K.Sprite.prototype.dispose = function(){
	this.removeEventListeners();
	if (this.graphics != null) {
		this.graphics.dispose();
		this.graphics = null;
	}
	if (this.src != null) {
		this.src.dispose();
		this.src = null;
	}
	var a = this.children.array;
	while (a.length > 0) {
		a.pop().dispose();
	}
	this.children.clear();
	this.parent = null;
};
K.Sprite.prototype.dispatchEvent = function(e){
	var el = e.clone();
	if (this.objListener[e.eventType]) {
		el.target = this;
		if (el.deviceType == "mouse" || el.deviceType == "touch") {
			if (this.hitTestPoint(el.data.mouseX, el.data.mouseY, this.mouseHitMethod)){
				el.currentTarget = this;
				this.broadcastEvent(el);
				return true;
			}
		} else {
			el.currentTarget = this;
			this.broadcastEvent(el);
		}
	}
	var hit = false;
	if (el.bubble) {
		var a = this.children.array;
		if (a.length > 0) {
			while (a.length > 0) {
				if (a.pop().dispatchEvent(el)) hit = true;
			}
		}
	}
	el.dispose();
	return hit;
};



K.SpriteSheet = function(name, x, y, sheet, curanim, curframe){
	this.initialize(name, { x:x, y:y, sheet:sheet, animName:curanim, cFrame:curframe-1, cTime:K.curTime });
};
K.SpriteSheet.prototype = K.cloneObject(K.Sprite.prototype);
K.SpriteSheet.prototype.constructor = K.SpriteSheet;
K.SpriteSheet.prototype.sheet = null;
K.SpriteSheet.prototype.animName = null;
K.SpriteSheet.prototype.cFrame = null;
K.SpriteSheet.prototype.cTime = null;
K.SpriteSheet.prototype.onAnimationEnd = function(v) { 
	alert(this.name + " animation end. Current frame " + v + ". We suggest you to override onAnimationEnd() or set prevAnim / nextAnim in AnimationData");
};
K.SpriteSheet.prototype.setFrame = function(v) {
	if (v < 0) {
		this.onAnimationEnd(this.animName);
		return;
	}
	if (v != this.cFrame) {
		this.cFrame = v;
		this.cTime = K.time.curTime;
		if (!this.sheet) {
			console.log(this.name + ".sheet not yet created");
			return;
		}
		if (!this.src) {
			this.src = this.sheet.createImageSource(v);
		} else {
			this.sheet.updateImageSource(this.src, v);
		}
		var v = this.src;
		this.localRect.x = v.offsetX;
		this.localRect.y = v.offsetY;
		this.localRect.width = v.width;
		this.localRect.height = v.height;
	}
};
K.SpriteSheet.prototype.__defineGetter__("frame", function() { return this.cFrame; });
K.SpriteSheet.prototype.__defineSetter__("frame", function(v) { this.setFrame(v); });
K.SpriteSheet.prototype.prevFrame = function() {
	this.currentFrame = this.sheet.checkFrame(this.animName, this.cFrame - 1);
};
K.SpriteSheet.prototype.nextFrame = function() {
	this.currentFrame = this.sheet.checkFrame(this.animName, this.cFrame + 1);
};
K.SpriteSheet.prototype.updateFrame = function(){
	if (!this.sheet) {
		console.log(this.name + ".sheet not yet created");
		return;
	}
	if (this.cTime == null) {
		this.cTime = K.time.curTime;
		this.frame = this.sheet.animation[this.animName].start;
	} else {
		this.frame = this.sheet.getFrame(this.animName, this.cFrame, this.cTime);
	}
};
K.SpriteSheet.prototype.dispose = function(){
	if (this.sheet != null) {
		this.sheet.dispose();
		this.sheet = null;
	}
	this.removeEventListeners();
	if (this.graphics != null) {
		this.graphics.dispose();
		this.graphics = null;
	}
	if (this.src != null) {
		this.src.dispose();
		this.src = null;
	}
	var a = this.children.array;
	while (a.length > 0) {
		a.pop().dispose();
	}
	this.children.clear();
	this.parent = null;
};


K.Stage = function(){
	this.initialize("Stage", {scaleMode:"noScale", align:"topLeft", orientation:"landScape"});
};
K.Stage.prototype = K.cloneObject(K.Sprite.prototype);
K.Stage.prototype.constructor = K.Stage;
K.Stage.prototype.originHeight = 0;
K.Stage.prototype.originWidth = 0;
K.Stage.prototype.__defineGetter__("stageHeight", function() { return K.canvas.height || 0; });
K.Stage.prototype.__defineGetter__("stageWidth", function() { return K.canvas.width || 0; });
K.Stage.prototype.align = "topLeft";
K.Stage.prototype.scaleMode = "showAll";
K.Stage.prototype.orientation = "landscape";
K.Stage.prototype.dispatchEvent = function(e){
	var el = e.clone();
	el.target = this;
	this.broadcastEvent(el);
	if (el.bubble) {
		var a = this.children.array;
		if (a.length > 0) {
			while (a.length > 0) {
				a.pop().dispatchEvent(el);
			}
		}
	}
	el.dispose();
};
K.Stage.prototype.hitTestPoint = function(x, y, inpixel){
	if (x < 0) return false;
	if (y < 0) return false;
	if (x > stageWidth) return false;
	if (y > stageHeight) return false;
	return true;
};
K.Stage.prototype.hitTestObject = function(obj, inpixel){
	return K.viewport,intersects(obj.worldRect);
};
K.stage = new K.Stage();

/*
** Do we need it ?
*/
K.Bitmap = function(name, x, y, src){
	this.initialize( name, {x:x, y:y, imageSource:src} );
};
K.Bitmap.prototype = K.cloneObject(K.Sprite.prototype);
K.Bitmap.prototype.constructor = K.Bitmap;

